<?php
namespace Illuminate\Auth;

use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Str;

class EloquentUserProvider implements UserProvider {
    protected $hasher; // \Illuminate\Contracts\Hashing\Hasher
    protected $model;

    public function __construct(HasherContract $hasher, $model) {
        $this->model = $model;
        $this->hasher = $hasher;
    }

    public function retrieveById($identifier) {
        $model = $this->createModel();

        return $model->newQuery()
            ->where($model->getAuthIdentifierName(), $identifier)
            ->first();
    }
    public function retrieveByToken($identifier, $token) {
        $model = $this->createModel();

        $model = $model->where($model->getAuthIdentifierName(), $identifier)->first();

        if ( ! $model ) return null;

        $rememberToken = $model->getRememberToken();

        return $rememberToken && hash_equals($rememberToken, $token) ? $model : null;
    }
    public function retrieveByCredentials(array $credentials) {
        if ( empty($credentials) ||
           (count($credentials) === 1 &&
            array_key_exists('password', $credentials)) ) return;

        $query = $this->createModel()->newQuery();

        foreach ( $credentials as $key => $value ) {
            if ( Str::contains($key, 'password') ) continue;

            if ( is_array($value) || $value instanceof Arrayable ) {
                $query->whereIn($key, $value);
            } else {
                $query->where($key, $value);
            }
        }

        return $query->first();
    }

    public function updateRememberToken(UserContract $user, $token) { // 更新 RememberToken
        $user->setRememberToken($token);
        $timestamps = $user->timestamps;
        $user->timestamps = false;
        $user->save();

        $user->timestamps = $timestamps;
    }
    public function validateCredentials(UserContract $user, array $credentials) { // 验证密码
        $plain = $credentials['password'];

        return $this->hasher->check($plain, $user->getAuthPassword());
    }

    public function createModel() { // 创建模型
        $class = '\\'.ltrim($this->model, '\\');

        return new $class;
    }

    public function getHasher() {
        return $this->hasher;
    }
    public function setHasher(HasherContract $hasher) {
        $this->hasher = $hasher;

        return $this;
    }
    public function getModel() {
        return $this->model;
    }
    public function setModel($model) {
        $this->model = $model;

        return $this;
    }
}
